﻿//
//    Copyright 2016 KeyleXiao.
//    Contact to Me : Keyle_xiao@hotmail.com 
//
//   	Licensed under the Apache License, Version 2.0 (the "License");
//   	you may not use this file except in compliance with the License.
//   	You may obtain a copy of the License at
//
//   		http://www.apache.org/licenses/LICENSE-2.0
//
//   		Unless required by applicable law or agreed to in writing, software
//   		distributed under the License is distributed on an "AS IS" BASIS,
//   		WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   		See the License for the specific language governing permissions and
//   		limitations under the License.
//
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;
using IGeneratorContract;
using ConfigGeneratorV2UI.Config;
using System.Collections.Generic;

namespace ConfigGeneratorV2UI.ExcelReader
{
    public class ExcelReaderProcess : IDisposable
    {
        private string fileName = null;
        private IWorkbook workbook = null;
        private FileStream fs = null;
        public int cellCount;
        public int rowCount;
        List<IExcelModel> ExcelInfos { get; set; }

        public ExcelReaderProcess(string fileName)
        {
            this.fileName = fileName;
            ExcelInfos = new List<IExcelModel>();
        }

        public List<IExcelModel> GetExcelInfo(out string msg)
        {
            msg = "";

            try
            {
                fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);

                if (fileName.IndexOf(".xlsx") > 0)
                    workbook = new XSSFWorkbook(this.fs);
                else if (fileName.IndexOf(".xls") > 0)
                    workbook = new HSSFWorkbook(this.fs);
                else return null;

                //get all sheets
                string tempOutputMsg = string.Empty;
                for (int i = 0; i < workbook.NumberOfSheets; i++)
                {
                    tempOutputMsg = string.Empty;
                    var excelinfo = GetExcelInfoBySheetName(workbook.GetSheetAt(i),out tempOutputMsg);
                    msg = string.Format("{0} \n{1} : {2}",msg, excelinfo.SheetName, string.IsNullOrEmpty(tempOutputMsg)?"No Error": tempOutputMsg);
                    excelinfo.WorkBookName = Path.GetFileNameWithoutExtension(fileName);//Set WorkBook Name
                    ExcelInfos.Add(excelinfo);
                }

                return ExcelInfos;
            }
            catch (Exception ex)
            {
                msg = "Exception: " + ex.Message;
            }

            return null;
        }


        //Get Sheet Info 
        public IExcelModel GetExcelInfoBySheetName(ISheet sheet, out string msg) {
            msg = string.Empty;

            var ExcelInfo = new ExcelModel();

            if (sheet == null) return null;
            int num = 0;

            //This row is title row 
            IRow row = sheet.GetRow(0);

            cellCount = row.LastCellNum;
            rowCount = sheet.LastRowNum;

            //Get title type is string
            for (int i = (int)row.FirstCellNum; i < this.cellCount; i++)
            {
                ICell cell = row.GetCell(i);
                if (cell != null)
                {
                    string stringCellValue = cell.StringCellValue;
                    if (!string.IsNullOrWhiteSpace(stringCellValue))
                    {
                        if (ExcelInfo.ColumnName.Contains(stringCellValue))
                        {
                            msg = string.Format("The Lsit Has The Same Column Title ,Name '{0}' ", stringCellValue);
                            return null;
                        }
                        ExcelInfo.ColumnName.Add(stringCellValue);
                    }
                    else
                        ExcelInfo.ColumnName.Add(string.Format("Column{0}", i));
                }
            }

            //num = sheet.FirstRowNum + 1;
            row = sheet.GetRow(1);

            //Get types as list
            for (int i = row.FirstCellNum; i < cellCount; i++)
            {
                ICell cell = row.GetCell(i);
                if (cell != null)
                {
                    string stringCellValue = cell.StringCellValue.ToUpper();
                    if (!string.IsNullOrWhiteSpace(stringCellValue))
                    {
                        switch (stringCellValue)
                        {
                            case "STRING":
                                ExcelInfo.ColumnType.Add(typeof(string));
                                break;
                            case "FLOAT":
                                ExcelInfo.ColumnType.Add(typeof(float));
                                break;
                            case "INT":
                                ExcelInfo.ColumnType.Add(typeof(int));
                                break;
                            case "STRING[]":
                                ExcelInfo.ColumnType.Add(typeof(string[]));
                                break;
                            case "FLOAT[]":
                                ExcelInfo.ColumnType.Add(typeof(float[]));
                                break;
                            case "INT[]":
                                ExcelInfo.ColumnType.Add(typeof(int[]));
                                break;
                            default:
                                msg = string.Format("Cant find the Type '{0}'  ,  Please check the document  : ) ", stringCellValue);
                                return null;
                        }
                    }
                    else
                    {
                        ExcelInfo.ColumnType.Add(typeof(string));
                    }
                }
            }

            num = sheet.FirstRowNum + 2;

            for (int i = num; i <= this.rowCount; i++)
            {
                IRow row2 = sheet.GetRow(i);
                if (row2 != null)
                {
                    List<string> items = new List<string>();
                    for (int j = (int)row2.FirstCellNum; j < this.cellCount; j++)
                    {
                        if (row2.GetCell(j) != null)
                        {
                            items.Add(row2.GetCell(j).ToString());
                        }
                    }
                    ExcelInfo.Rows.Add(i, items);
                }
            }

            ExcelInfo.SheetName = sheet.SheetName;

            return ExcelInfo;
        }


        public void Dispose()
        {
            if (this.fs != null)
            {
                this.fs.Close();
            }
            fs = null;
            GC.SuppressFinalize(this);
        }
    }
}
